package gstudio.data;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.eclipse.jface.dialogs.MessageDialog;

public class DataIO {

	private String currentPath, gsRootPath, xmlFilePath, mp3Dir, tempDir;

	private static DataIO dataIO;

	public static DataIO getInstance() {
		if (dataIO == null)
			dataIO = new DataIO();
		return dataIO;
	}

	private DataIO() {
		currentPath = new File("").getAbsolutePath();
		xmlFilePath = currentPath + "/gstudio/data.xml";

		gsRootPath = currentPath + "/gstudio";
		File file = new File(gsRootPath);
		if (!file.isDirectory()) {
			file.mkdir();
		}

		gsRootPath = file.getAbsolutePath();
		mp3Dir = gsRootPath + "/mp3";
		file = new File(mp3Dir);
		if (!file.isDirectory()) {
			file.mkdir();
		}
		mp3Dir = file.getAbsolutePath();

		tempDir = gsRootPath + "/temp";
		file = new File(tempDir);
		if (!file.isDirectory()) {
			file.mkdir();
		}
		tempDir = file.getAbsolutePath();
	}

	@SuppressWarnings("resource")
	public boolean copyFile(File f1, File f2) {
		int length = 2097152;
		FileInputStream in;
		try {
			in = new FileInputStream(f1);

			FileOutputStream out = new FileOutputStream(f2);
			FileChannel inC = in.getChannel();
			FileChannel outC = out.getChannel();
			ByteBuffer b = null;
			while (true) {
				if (inC.position() == inC.size()) {
					inC.close();
					outC.close();
				}
				if ((inC.size() - inC.position()) < length) {
					length = (int) (inC.size() - inC.position());
				} else
					length = 2097152;
				b = ByteBuffer.allocateDirect(length);
				inC.read(b);
				b.flip();
				outC.write(b);
				outC.force(false);
				return true;
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
	}

	public void createMp3SubDir(String name) {
		File file = new File(mp3Dir + "/" + name);
		if (!file.isDirectory()) {
			file.mkdir();
		}
	}

	public String getCurrentPath() {
		return currentPath;
	}

	public String getGsRootPath() {
		return gsRootPath;
	}

	public String getMp3Dir() {
		return mp3Dir;
	}

	public String getTempDir() {
		return tempDir;
	}

	public String getXmlFilePath() {
		return xmlFilePath;
	}

	public boolean loadFile() {
		File file = new File(xmlFilePath);
		if (!file.canRead()) {
			return true;
		}

		try {
			SAXReader reader = new SAXReader();
			Document doc = reader.read(file);
			Element root = doc.getRootElement();
			RuntimeDataManager runtimedata = RuntimeDataManager.getInstance();
			Node artikels = root.selectSingleNode("artikels");
			runtimedata.setArtikelList(readElement(artikels, "artikel"));
			Node satzs = root.selectSingleNode("satzs");
			runtimedata.setSatzList(readElement(satzs, "satz"));
			Node worts = root.selectSingleNode("worts");
			runtimedata.setWortList(readElement(worts, "wort"));

			return true;
		} catch (DocumentException e) {
			e.printStackTrace();
			return false;
		}
	}

	private List<IData> readElement(Node parent, String childName) {
		List<IData> list = new ArrayList<IData>();
		if (parent == null)
			return list;
		IData idata;
		for (Object obj : parent.selectNodes(childName)) {
			Node node = (Node) obj;
			idata = new IData();
			for (String key : idata.getKeys()) {
				Node n = node.selectSingleNode(key);
				if (n != null) {
					idata.setValueOf(key, n.getText());
				}
			}

			list.add(idata);
		}
		return list;
	}

	public void saveXML() {
		Document doc = DocumentHelper.createDocument();
		doc.setXMLEncoding("utf-8");

		Element root = doc.addElement("root");

		List<IData> list = RuntimeDataManager.getInstance().getArtikelList();
		Element artikels = root.addElement("artikels");
		writeDocument(doc, list, artikels, "artikel");

		list = RuntimeDataManager.getInstance().getSatzList();
		Element satzs = root.addElement("satzs");
		writeDocument(doc, list, satzs, "satz");

		list = RuntimeDataManager.getInstance().getWortlList();
		Element worts = root.addElement("worts");
		writeDocument(doc, list, worts, "wort");
		writeDoc(doc);
	}

	public void writeDoc(Document doc) {
		writeDoc(doc, xmlFilePath);
	}

	private void writeDocument(Document doc, List<IData> list, Element parent,
			String elementName) {

		for (IData idata : list) {
			Element e = parent.addElement(elementName);
			for (String key : idata.getKeys()) {
				Element elem = e.addElement(key);
				elem.setText(idata.getValueOf(key));
			}

		}
	}

	public void writeDoc(Document doc, String string) {
		try {

			OutputFormat of = new OutputFormat();
			of.setIndent(true);
			of.setNewlines(true);
			Writer writer = new OutputStreamWriter(
					new FileOutputStream(string), "UTF-8");
			XMLWriter xmlWriter = new XMLWriter(writer, of);
			xmlWriter.write(doc);
			xmlWriter.close();
			MessageDialog.openInformation(null, null, string + " ok!");
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

}
